import { createAlova, Method } from 'alova';
import fetchAdapter from 'alova/fetch';
import { Toast } from '@douyinfe/semi-ui';
import type { HttpGetOptions, HttpResponsor, ReturnResult } from '@/types/http';
import { router } from '@/router';
import { getOriginToken } from '@/utils/token';

const BASE_URL = '/admin-api';
const RAM_BASE_URL = '/ram-api';

const beforeRequest = (method: Method) => {
  const token = getOriginToken();
  method.config.headers['x-Auth-Token'] = token;
  method.config.headers['X-Request-Time'] = Date.now();
}

export function httpGet<ResponseData = any>(options: Partial<HttpGetOptions>) {
  const alovaInstance = createAlova({
    baseURL: BASE_URL,
    requestAdapter: fetchAdapter(),
    beforeRequest,
  });

  const url = options.url ?? '';
  const params = Object.fromEntries(new URLSearchParams(options.params ?? ''));
  const queryString = Object.keys(params).length
    ? `?${Object.keys(params).map(item => `${item}=${params[item]}`).join('&')}`
    : ''

  return new Promise<ResponseData>((resolve, reject) => {
    alovaInstance
      .Get<HttpResponsor<ResponseData>>(`${url}${queryString}`, params)
      .then((resp) => resolve(responseHttpData(resp)))
      .catch(e => reject(e));
  })
}

export function httpPost<ResponseData = any>(options: Partial<HttpGetOptions>) {
  const alovaInstance = createAlova({
    baseURL: BASE_URL,
    requestAdapter: fetchAdapter(),
    beforeRequest,
  });

  const url = options.url ?? '';
  const data = options.params ?? {};

  return new Promise<ResponseData>((resolve, reject) => {
    alovaInstance
      .Post<HttpResponsor<ResponseData>>(url, data)
      .then((resp) => resolve(responseHttpData(resp)))
      .catch(e => reject(e));
  });
}

export function httpPut<ResponseData = any>(options: Partial<HttpGetOptions>) {
  const alovaInstance = createAlova({
    baseURL: BASE_URL,
    requestAdapter: fetchAdapter(),
    beforeRequest,
  });

  const url = options.url ?? '';
  const data = options.params ?? {};

  return new Promise<ResponseData>((resolve, reject) => {
    alovaInstance
      .Put<HttpResponsor<ResponseData>>(url, data)
      .then((resp) => resolve(responseHttpData(resp)))
      .catch(e => reject(e));
  });
}

export function httpDelete<ResponseData = any>(options: Partial<HttpGetOptions>) {
  const alovaInstance = createAlova({
    baseURL: BASE_URL,
    requestAdapter: fetchAdapter(),
    beforeRequest,
  });

  const url = options.url ?? '';
  const data = options.params ?? {};

  return new Promise<ResponseData>((resolve, reject) => {
    alovaInstance.Delete<HttpResponsor<ResponseData>>(url, data)
      .then((resp) => resolve(responseHttpData(resp)))
      .catch(e => reject(e));
  });
}

export function ramHttpPost<ResponseData = any>(options: Partial<HttpGetOptions>) {
  const alovaInstance = createAlova({
    baseURL: RAM_BASE_URL,
    requestAdapter: fetchAdapter(),
    beforeRequest,
  });

  const url = options.url ?? '';
  const data = options.params ?? {};

  return new Promise<ResponseData>((resolve, reject) => {
    alovaInstance
      .Post<HttpResponsor<ResponseData>>(url, data)
      .then((resp) => resolve(resp.json()))
      .catch(e => reject(e));
  });
}

async function responseHttpData <ResponseData = any> (resp: HttpResponsor<ResponseData>) {
  const response: Awaited<ResponseData> & ReturnResult =
    await resp.json() as Awaited<ResponseData> & ReturnResult;

  if ([401, 403].includes(response.code)) {
    Toast.error('登录信息已失效，请重新登录！');
    setTimeout(() => {
      router.navigate('/common/login');
    }, 2000);
  }

  return response;
}
